package com.carp.shard.plugin.strategy;

import lombok.NonNull;

import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 分片策略上下文
 *
 * @author lile
 * @since 2024/5/10
 */
public class ShardStrategyContext {

    /**
     * 分片策略映射
     */
    private static final Map<String, AbstractShardStrategy> MAPPINGS = new ConcurrentHashMap<>();

    static {
        registerStrategy(DefaultShardStrategy.TABLE_NAME, DefaultShardStrategy.INSTANCE);
    }

    /**
     * 注册策略到上下文
     *
     * @param tableName 表名
     * @param strategy  分片策略
     */
    public static void registerStrategy(@NonNull String tableName, @NonNull AbstractShardStrategy strategy) {
        MAPPINGS.putIfAbsent(tableName, strategy);
    }

    /**
     * 根据表名获取分片策略
     *
     * @param tableName 表名
     * @return 分片策略
     */
    public static AbstractShardStrategy getStrategyByTableName(@NonNull String tableName) {
        return Optional.ofNullable(MAPPINGS.get(handleName(tableName)))
                .orElse(MAPPINGS.get(DefaultShardStrategy.TABLE_NAME));
    }

    /**
     * 获取原始表名
     *
     * @param ident SQL中的表名
     * @return 原始表名
     */
    private static String handleName(String ident) {
        int len = ident.length();
        if (ident.charAt(0) == '[' && ident.charAt(len - 1) == ']') {
            ident = ident.substring(1, len - 1);
        } else {
            boolean flag0 = false;
            boolean flag1 = false;
            boolean flag2 = false;
            boolean flag3 = false;
            for (int i = 0; i < len; ++i) {
                final char ch = ident.charAt(i);
                if (ch == '\"') {
                    flag0 = true;
                } else if (ch == '`') {
                    flag1 = true;
                } else if (ch == ' ') {
                    flag2 = true;
                } else if (ch == '\'') {
                    flag3 = true;
                }
            }
            if (flag0) {
                ident = ident.replaceAll("\"", "");
            }

            if (flag1) {
                ident = ident.replaceAll("`", "");
            }

            if (flag2) {
                ident = ident.replaceAll(" ", "");
            }

            if (flag3) {
                ident = ident.replaceAll("'", "");
            }
        }
        return ident;
    }

}
